import Vue from "vue";
const isServer = Vue.prototype.$isServer;

export function dateFormat(fmt, date) {
	var o = {
		"M+": date.getMonth() + 1, //月份
		"d+": date.getDate(), //日
		"H+": date.getHours(), //小时
		"h+": date.getHours(), //小时
		"m+": date.getMinutes(), //分
		"s+": date.getSeconds(), //秒
		"q+": Math.floor((date.getMonth() + 3) / 3), //季度
		"S": date.getMilliseconds() //毫秒
	};
	if (/(y+)/.test(fmt)) {
		fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
	}
	for (var k in o) {
		if (new RegExp("(" + k + ")").test(fmt)) {
			fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
		}
	}
	return fmt;
};
export function getStartTime(time) {
	let date = new Date(time)
	date.setHours(0, 0, 0, 0)
	return dateFormat("yyyy-MM-dd hh:mm:ss", date)
}
export function getEndTime(time) {
	let date = new Date(time)
	date.setHours(23, 59, 59, 999)
	return dateFormat("yyyy-MM-dd hh:mm:ss", date)
}
export function dateDefault(date) {
	let fmt = 'yyyy-MM-dd hh:mm:ss'
	var o = {
		"M+": date.getMonth() + 1, //月份
		"d+": date.getDate(), //日
		"H+": date.getHours(), //小时
		"h+": date.getHours(), //小时
		"m+": date.getMinutes(), //分
		"s+": date.getSeconds(), //秒
		"q+": Math.floor((date.getMonth() + 3) / 3), //季度
		"S": date.getMilliseconds() //毫秒
	};
	if (/(y+)/.test(fmt)) {
		fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
	}
	for (var k in o) {
		if (new RegExp("(" + k + ")").test(fmt)) {
			fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
		}
	}
	return fmt;
};
var dayjs = require('dayjs')
// 根据传递过来的数据得到过去的日期,num多少，type为"day,mouth,year等"
export function getPastDate(num, type) {
	let date = dayjs().subtract(num, type)
	return dateDefault(new Date(date));
}
// 得到未来的日期
export function getNextDate(num, type) {
	let date = dayjs().add(num, type)
	return dateDefault(new Date(date));
}
// 得到未来多少天的日期
export function getDateFromFutureDay(day) {
	return dayjs().add(day, 'day').format('YYYY-MM-DD');
}
// 计算两个日期之间的天数
export function getDaysBetweenDates(startDay, endDay) {
	if (!startDay) {
		return 0
	}
	let start = dateFormat("yyyy-MM-dd", new Date(startDay))
	start = new Date(start)
	let end = dateFormat("yyyy-MM-dd", new Date(endDay))
	end = new Date(end)
	let millisecondsBetween = end.getTime() - start.getTime();
	return Math.floor(millisecondsBetween / (60 * 60 * 24 * 1000))
}
// 得到时间是否大于今天的天数,为正数表示大于今天多少天，为负数表示小于今天多少天
export function getFutureDays(date) {
	let inDate = dateFormat("yyyy-MM-dd", new Date(date))
	inDate = new Date(inDate)
	let nowDate = dateFormat("yyyy-MM-dd", new Date())
	nowDate = new Date(nowDate)
	let millisecondsBetween = inDate.getTime() - nowDate.getTime();
	return Math.floor(millisecondsBetween / (60 * 60 * 24 * 1000));
}
// 得到当前日期和现在之间的秒数,为正数表示大于现在多少秒，负数表示小于现在多少秒
export function getFutureSeconds(date) {
	let inDate = dateFormat("yyyy-MM-dd HH:mm:ss", new Date(date))
	inDate = new Date(inDate)
	let nowDate = dateFormat("yyyy-MM-dd HH:mm:ss", new Date())
	nowDate = new Date(nowDate)
	let millisecondsBetween = inDate.getTime() - nowDate.getTime();
	return Math.floor(millisecondsBetween / 1000);
}
// 根据传递的秒数得到日期，正数为将来多少秒的日期，负数表示多少秒之前的日期
export function getDateBySecond(second) {
	let date = new Date().getTime()
	let nowTime = date + second * 1000;
	date = new Date(nowTime)
	return dateDefault(date);
}
export function getYearsBetweenDates(date1, date2) {
	// 确保date1早于date2
	if (date1 > date2) {
		[date1, date2] = [date2, date1];
	}

	// 将日期转换为毫秒并计算差值
	let millisecondsBetween = date2.getTime() - date1.getTime();
	// 将毫秒转换为年（考虑每一年大约有365.25天，即31556952毫秒）
	let years = Math.floor(millisecondsBetween / (1000 * 60 * 60 * 24 * 365.25));
	return years;
}
export function getSecondBetweenDates(date1, date2) {
	// 确保date1早于date2
	if (date1 > date2) {
		[date1, date2] = [date2, date1];
	}

	// 将日期转换为毫秒并计算差值
	let millisecondsBetween = date2.getTime() - date1.getTime();
	// 将毫秒转换为年（考虑每一年大约有365.25天，即31556952毫秒）
	let second = Math.floor(millisecondsBetween / 1000);
	return second;
}
// 判断参数是否是其中之一
export function oneOf(value, validList) {
	for (let i = 0; i < validList.length; i++) {
		if (value === validList[i]) {
			return true;
		}
	}
	return false;
}

export function camelcaseToHyphen(str) {
	return str.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
}

// For Modal scrollBar hidden
let cached;
export function getScrollBarSize(fresh) {
	if (isServer) return 0;
	if (fresh || cached === undefined) {
		const inner = document.createElement("div");
		inner.style.width = "100%";
		inner.style.height = "200px";

		const outer = document.createElement("div");
		const outerStyle = outer.style;

		outerStyle.position = "absolute";
		outerStyle.top = 0;
		outerStyle.left = 0;
		outerStyle.pointerEvents = "none";
		outerStyle.visibility = "hidden";
		outerStyle.width = "200px";
		outerStyle.height = "150px";
		outerStyle.overflow = "hidden";

		outer.appendChild(inner);

		document.body.appendChild(outer);

		const widthContained = inner.offsetWidth;
		outer.style.overflow = "scroll";
		let widthScroll = inner.offsetWidth;

		if (widthContained === widthScroll) {
			widthScroll = outer.clientWidth;
		}

		document.body.removeChild(outer);

		cached = widthContained - widthScroll;
	}
	return cached;
}

// watch DOM change
export const MutationObserver = isServer ?
	false :
	window.MutationObserver ||
	window.WebKitMutationObserver ||
	window.MozMutationObserver ||
	false;

// firstUpperCase
function firstUpperCase(str) {
	return str.toString()[0].toUpperCase() + str.toString().slice(1);
}
export {
	firstUpperCase
};

// Warn
export function warnProp(component, prop, correctType, wrongType) {
	correctType = firstUpperCase(correctType);
	wrongType = firstUpperCase(wrongType);
	console.error(
		`[iView warn]: Invalid prop: type check failed for prop ${prop}. Expected ${correctType}, got ${wrongType}. (found in component: ${component})`
	); // eslint-disable-line
}

function typeOf(obj) {
	const toString = Object.prototype.toString;
	const map = {
		"[object Boolean]": "boolean",
		"[object Number]": "number",
		"[object String]": "string",
		"[object Function]": "function",
		"[object Array]": "array",
		"[object Date]": "date",
		"[object RegExp]": "regExp",
		"[object Undefined]": "undefined",
		"[object Null]": "null",
		"[object Object]": "object"
	};
	return map[toString.call(obj)];
}
export {
	typeOf
};

// deepCopy
function deepCopy(data, index, len) {
	const t = typeOf(data);
	let o;

	// 这个 if 是自己加的, 如果尝试失败，则忽略index，然后继续之前的步骤
	if (index != undefined && t === "array" && typeOf(index) === 'number') {
		if (index < 0) {
			index += data.length;
		}
		if (len && typeOf(len) === 'number') {
			o = [];
			for (let i = index; i < index + len; i++) {
				o.push(deepCopy(data[i]));
			}
			return o;
		} else {
			if (index >= 0 && index < data.length) {
				return deepCopy(data[index]);
			}
		}
	}

	if (t === "array") {
		o = [];
	} else if (t === "object") {
		o = {};
	} else {
		return data;
	}

	if (t === "array") {
		for (let i = 0; i < data.length; i++) {
			o.push(deepCopy(data[i]));
		}
	} else if (t === "object") {
		for (let i in data) {
			o[i] = deepCopy(data[i]);
		}
	}
	return o;
}
export {
	deepCopy
};

/** ### 复制对象
 * #### 可： 指定或排除 指定属性
 * 例如：b = deepCopyObj(a,['a','b'],null)
 */
export function deepCopyObj(data, containPorp, removePorp) {
	if (typeOf(data) !== "object") {
		return null;
	}

	let o = {};

	for (const key in data) {
		if (data.hasOwnProperty(key)) {

			if (!isEmptyData(containPorp)) {
				if (containPorp.includes(key)) {
					o[key] = deepCopy(data[key]);
				}
			} else {
				if (!removePorp.includes(key)) {
					o[key] = deepCopy(data[key]);
				}
			}
		}
	}

	return o;
}

// null,undefined,'',{},[]  => 返回true
export function isEmptyData(val) {
	if (!val ||
		val === '' ||
		(Array.isArray(val) && val.length === 0) ||
		(Object.prototype.toString.call(val) === '[object Object]' && Object.keys(val).length === 0)) {
		return true;
	} else {
		return false;
	}
}

/*
1. 主要是为了避开 直接修改props的检测
*/
export function updateObj(dst, src, delPrivate = false) {
	for (let key in src) {
		dst[key] = src[key];
	}
	if (delPrivate) {
		for (let key in dst) {
			if (!src[key]) {
				delete dst[key];
			}
		}
	}
}


// scrollTop animation
export function scrollTop(el, from = 0, to, duration = 500, endCallback) {
	if (!window.requestAnimationFrame) {
		window.requestAnimationFrame =
			window.webkitRequestAnimationFrame ||
			window.mozRequestAnimationFrame ||
			window.msRequestAnimationFrame ||
			function(callback) {
				return window.setTimeout(callback, 1000 / 60);
			};
	}
	const difference = Math.abs(from - to);
	const step = Math.ceil((difference / duration) * 50);

	function scroll(start, end, step) {
		if (start === end) {
			endCallback && endCallback();
			return;
		}

		let d = start + step > end ? end : start + step;
		if (start > end) {
			d = start - step < end ? end : start - step;
		}

		if (el === window) {
			window.scrollTo(d, d);
		} else {
			el.scrollTop = d;
		}
		window.requestAnimationFrame(() => scroll(d, end, step));
	}
	scroll(from, to, step);
}

// Find components upward
function findComponentUpward(context, componentName, componentNames) {
	if (typeof componentName === "string") {
		componentNames = [componentName];
	} else {
		componentNames = componentName;
	}

	let parent = context.$parent;
	let name = parent.$options.name;
	while (parent && (!name || componentNames.indexOf(name) < 0)) {
		parent = parent.$parent;
		if (parent) name = parent.$options.name;
	}
	return parent;
}
export {
	findComponentUpward
};

// Find component downward
export function findComponentDownward(context, componentName) {
	const childrens = context.$children;
	let children = null;

	if (childrens.length) {
		for (const child of childrens) {
			const name = child.$options.name;
			if (name === componentName) {
				children = child;
				break;
			} else {
				children = findComponentDownward(child, componentName);
				if (children) break;
			}
		}
	}
	return children;
}

// Find components downward
export function findComponentsDownward(
	context,
	componentName,
	ignoreComponentNames = []
) {
	if (!Array.isArray(ignoreComponentNames)) {
		ignoreComponentNames = [ignoreComponentNames];
	}
	return context.$children.reduce((components, child) => {
		if (child.$options.name === componentName) components.push(child);
		if (ignoreComponentNames.indexOf(child.$options.name) < 0) {
			const foundChilds = findComponentsDownward(child, componentName);
			return components.concat(foundChilds);
		} else {
			return components;
		}
	}, []);
}

// Find components upward
export function findComponentsUpward(context, componentName) {
	let parents = [];
	const parent = context.$parent;
	if (parent) {
		if (parent.$options.name === componentName) parents.push(parent);
		return parents.concat(findComponentsUpward(parent, componentName));
	} else {
		return [];
	}
}

// Find brothers components
export function findBrothersComponents(
	context,
	componentName,
	exceptMe = true
) {
	let res = context.$parent.$children.filter(item => {
		return item.$options.name === componentName;
	});
	let index = res.findIndex(item => item._uid === context._uid);
	if (exceptMe) res.splice(index, 1);
	return res;
}

/* istanbul ignore next */
const trim = function(string) {
	return (string || "").replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g, "");
};

/* istanbul ignore next */
export function hasClass(el, cls) {
	if (!el || !cls) return false;
	if (cls.indexOf(" ") !== -1)
		throw new Error("className should not contain space.");
	if (el.classList) {
		return el.classList.contains(cls);
	} else {
		return (" " + el.className + " ").indexOf(" " + cls + " ") > -1;
	}
}

/* istanbul ignore next */
export function addClass(el, cls) {
	if (!el) return;
	let curClass = el.className;
	const classes = (cls || "").split(" ");

	for (let i = 0, j = classes.length; i < j; i++) {
		const clsName = classes[i];
		if (!clsName) continue;

		if (el.classList) {
			el.classList.add(clsName);
		} else {
			if (!hasClass(el, clsName)) {
				curClass += " " + clsName;
			}
		}
	}
	if (!el.classList) {
		el.className = curClass;
	}
}

/* istanbul ignore next */
export function removeClass(el, cls) {
	if (!el || !cls) return;
	const classes = cls.split(" ");
	let curClass = " " + el.className + " ";

	for (let i = 0, j = classes.length; i < j; i++) {
		const clsName = classes[i];
		if (!clsName) continue;

		if (el.classList) {
			el.classList.remove(clsName);
		} else {
			if (hasClass(el, clsName)) {
				curClass = curClass.replace(" " + clsName + " ", " ");
			}
		}
	}
	if (!el.classList) {
		el.className = trim(curClass);
	}
}

export const dimensionMap = {
	xs: "480px",
	sm: "576px",
	md: "768px",
	lg: "992px",
	xl: "1200px",
	xxl: "1600px"
};

export function setMatchMedia() {
	if (typeof window !== "undefined") {
		const matchMediaPolyfill = mediaQuery => {
			return {
				media: mediaQuery,
				matches: false,
				on() {},
				off() {}
			};
		};
		window.matchMedia = window.matchMedia || matchMediaPolyfill;
	}
}

export const sharpMatcherRegx = /#([^#]+)$/;



// 获取随机 大写字符 format=[数字|小写|大写]
export function generateRandomStr(len, format) {
	len = len || 64;
	format = format || "数字"

	//
	var chars = '';
	if (format.includes('数字')) {
		chars += '1234567890'
	}
	if (format.includes('小写')) {
		chars += 'abcdefjhijklmnopqrstyvwxyz'
	}
	if (format.includes('大写')) {
		chars += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
	}
	var maxPos = chars.length;
	var pwd = '';
	for (var i = 0; i < len; i++) {
		pwd += chars.charAt(Math.floor(Math.random() * maxPos));
	}
	return pwd;
}

export function generateGuid() {
	return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
		var r = Math.random() * 16 | 0,
			v = c == 'x' ? r : (r & 0x3 | 0x8);
		return v.toString(16);
	});
}
/**
 * 根据对象的属性 进行升序或者降序排序
 * 调用示例：list.sort(compare(‘属性’,'desc/不传')); 
 * @param {} pro 
 * @param {*} order 
 * @returns 
 */
export function compare(pro, order) {
	return function(obj1, obj2) {
		let val1 = obj1[pro];
		let val2 = obj2[pro];
		if (order === 'desc') {
			undefined
			val1 = obj2[pro];
			val2 = obj1[pro];
		}
		if (val2 < val1) { //正序
			return 1;
		} else if (val2 > val1) {
			return -1;
		} else {
			return 0;
		}
	}
}
/**
 * 两个数组去重合并 (根据id)
 */
export function repeat(arr1, arr2) {
	let json = arr1.concat(arr2);
	let newJson = [];
	for (var i = 0; i < json.length; i++) {
		let flag = true;
		for (var j = 0; j < newJson.length; j++) {
			if (newJson[j].id == json[i].id) {
				flag = false;
			}
		}
		if (flag) { //判断是否重复
			newJson.push(json[i]);
		}
	}
	arr1 = newJson;
	return arr1

}